package com.thoughtworks.bytecode2class.attribute;

import com.thoughtworks.bytecode2class.ClassReader;
import com.thoughtworks.bytecode2class.ExceptionInfo;

import java.util.ArrayList;
import java.util.List;

public class CodeAttribute extends Attribute {

    private int maxStack;
    private int maxLocals;
    private int codeLength;
    private int exceptionTableLength;
    private int attributesCount;
    private List<ExceptionInfo> exceptionTable;
    private List<Attribute> attributes;
    private Code code;

    public CodeAttribute(ClassReader classReader, String name) {
        super(classReader, name);
    }

    protected void parseAttributeContent() {
        parseMaxStack();
        parseMaxLocals();
        parseCodeLength();
        parseCode();
        parseExceptionTableLength();
        parseExceptionTable();
        parseAttributesCount();
        parseAttributes();
    }

    private void parseAttributes() {
        for (int i = 0; i < this.attributesCount; i++) {
            attributes.add(Attribute.create(classReader));
        }
    }

    private void parseAttributesCount() {
        this.attributesCount = classReader.forwardChar();
        attributes = new ArrayList<Attribute>(attributesCount);
    }

    private void parseExceptionTableLength() {
        this.exceptionTableLength = classReader.forwardChar();
        exceptionTable = new ArrayList<ExceptionInfo>(exceptionTableLength);
    }

    private void parseExceptionTable() {
        for (int i = 0; i < exceptionTableLength; i++) {
            exceptionTable.add(new ExceptionInfo(classReader));
        }
    }

    private void parseCode() {
        List<Byte> allCode = classReader.forwardBytes(codeLength);
        code = Code.create(allCode);
    }

    private void parseCodeLength() {
        this.codeLength = classReader.forwardWord();
    }

    private void parseMaxLocals() {
        this.maxLocals = classReader.forwardChar();
    }

    private void parseMaxStack() {
        this.maxStack = classReader.forwardChar();
    }

    public int getMaxStack() {
        return maxStack;
    }

    public int getMaxLocals() {
        return maxLocals;
    }

    public int getCodeLength() {
        return codeLength;
    }

    public Code getCode() {
        return code;
    }

    public int getExceptionTableLength() {
        return exceptionTableLength;
    }

    public int getAttributesCount() {
        return attributesCount;
    }

    public List<ExceptionInfo> getExceptionTable() {
        return exceptionTable;
    }
}
